HTTP Request 是一個在 HTTP Protocol 中定義的資料傳遞方式。
在 Laravel 中,簡化了這樣的資料獲取模式,比起 $_GET
或 $_POST
,它在使用上更加容易
<?php
// app/Http/Controllers/WelcomeController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class WelcomeController extends Controller
{
public function __invoke(Request $request)
{
// 無論是來自於 GET 或 POST,甚至是路由參數,都可以直接取得值
$request->user_id;
// 對於可能不存在的值,可以用第二個參數設定預設值
$request->input('name', 'World');
// 對於比較複雜的資料(如陣列或 JSON),可以用 input 輔助取得值
$request->input('user.name');
}
}
Request 還有許多其它的用法,如檔案上傳或是 Cookie 等,礙於篇幅不一一說明,這部份應該參閱官方文件。
在 Laravel 中,我們可以簡單地驗證資料是否符合我們的需求。
<?php
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
$validator = Validator::make(['name' => 'Jack'], [
'name' => 'required|string'
]);
if ($validator->fails()) {
// 驗證失敗的情況
throw new ValidationException($validator);
}
使用 Validator
時,第一個參數是「想要驗證的資料」,第一個參數則是「驗證的規則」。
驗證規則中,Key 表示要驗證的欄位,Value 表示驗證的規則,Value 大部份時候可以是 |
分隔的規則字串,或是一個陣列。
<?php
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(['name' => 'Jack'], [
'name' => ['required', 'string'],
]);
// ...
對於多維陣列,可以在規則中加入 .
做設計。
<?php
use Illuminate\Support\Facades\Validator;
$validator = Validator::make(['user' => ['name' => 'Jack']], [
'user' => 'required|array',
'user.name' => 'required|string',
]);
在 Controller 中通常會頻繁使用到 Validation,所以我們可以利用 $request->validate()
進行驗證
<?php
// ...
class WelcomeController extends Controller
{
public function __invoke(Request $request)
{
$request->validate(['name' => 'required|string']);
// 驗證失敗後,會自動丟出 ValidationException,到這邊能夠確定 name 存在且為 string
$request->name;
}
}
對於較複雜的情況,我們可以建立一個獨立的 FormRequest 編寫規則
$ php artisan make:request [request-name]
剛建立好的 FormRequest 位於 app/Http/Requests
之中,內容大致類似於
<?php
// app/Http/Requests/ExampleRequest.php
// ...
public function authorize()
{
return false;
}
public function rules()
{
return [
//
];
}
// ...
使用時,將 authorize()
改為 true
,並在 rules()
中編寫驗證邏輯即可。
註:
authroize()
這個 method 是用於驗證使用者是否能進行此 Request。
<?php
// app/Http/Requests/AdminRequest.php
public function authorize()
{
// 如此一來,只要不是 Admin 的用戶就不能執行這個 Request
return $this->user()->isAdmin();
}
最後,在 Controller 裡使用 FormRequest
<?php
// app/Http/Controllers/WelcomeController.php
// ...
use App\Http\Requests\ExampleRequest;
class WelcomeController extends Controller
{
public function __invoke(ExampleRequest $request)
{
// 此處的 $request 已經被驗證過,資料一定符合規則中所寫的
}
}
在 Controller 中使用 return view()
或是 return ['name' => 'Jack']
的方式回傳視圖或是 JSON,事實上它們是 Laravel 提供的語法糖,若要更細緻地操作 HTTP Response,應該使用 response()
<?php
// ...
public function __invoke(): Response
{
return response('Hello World', 202); // 設定 HTTP Status Code
}
有時候,我們在 HTTP Request 觸及到應用程式之前,需要先做一些檢查(例如確定用戶是已登入狀態),此時我們會用中介層去避免重複撰寫相同的邏輯。
中介層的運作邏輯可以用一張圖簡略概括
利用以下指令可以快速建立一個中介層
$ php artisan make:middleware [middleware-name]
剛建立的中介層位於 app/Http/Middleware
,內容大致如下(省略了 PHPDocs)
<?php
namespace App\Http\Middleware;
use Closure;
class ExampleMiddleware
{
public function handle($request, Closure $next)
{
return $next($request);
}
}
$request
是用戶請求的資料,在中介層中可以任意讀取或修改它(如果有需要的話)
如同上圖所示,中介層是一層層推疊起來的,所以參數中會有一個 $next
作為前往下一層的呼叫。
可以在 app/Http/Kernel.php
中指定要使用哪些中介層,內容大致如下
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
protected $middleware = [
// ...
];
protected $middlwareGroups = [
'web' => [
// ...
],
'api' => [
// ...
],
];
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
// ...
],
}
$middleware
property 表示所有的請求都會經過這些中介層。$middlewareGroups
,可以讓 web 路由經過指定的中介層,並讓 api 路由經過不同的中介層。(例如「啟動 Session」通常是只有 web 才會用到的功能,API 是不需要使用的)
routes/api.php
及 routes/web.php
的差異僅在使用的 Middleware Group 不同$routeMiddleware
中有指定某些中介層的別名,利於記憶與使用。可以在 Route 上指定要使用哪些中介層
<?php
Route::middleware('auth')->group(function () {
// 在這個區域內,僅有已登入的用戶才能存取
Route::get('/home', fn() => 'Hello World');
});
也可以在 Controller 中指定要使用哪些中介層
<?php
class WelcomeController extends Controller
{
public function __construct()
{
// 表示這個 Controller 中所有的 Method 都是已登入的用戶才能存取
$this->middleware('auth');
}
public function __invoke()
{
return 'Hello World';
}
}